export class UITools {
  static hideOriginTopNav(hide = true): boolean {
    const header: HTMLElement | null = document.querySelector("#header");
    if (!header) {
      return false;
    }
    if (hide) {
      header.style.display = "none";
    } else {
      header.style.display = "block";
    }
    return true;
  }
}

export class GetAsyncDomUtil {
  index: number;
  iterLimit: number;
  target: string;
  purpose: string;
  condition: boolean | ((...e: any) => any);
  fn: () => any;
  time: number;
  instantMode: boolean;
  maxWaitTime: number;
  insure: undefined;
  probeTimeHandler: number;
  extraParam: null;
  devMode: boolean;

  constructor(
    target: string,
    fn: () => any,
    insure: null | undefined,
    purpose = "exist",
    time = 2500,
    instantMode = true,
    maxWaitTime = 30000,
    devMode = true,
    extraParam = null
  ) {
    this.index = 0;
    this.iterLimit = 0;
    this.target = target;
    this.purpose = purpose;
    this.condition = true;
    this.fn = typeof fn === "function" ? fn : this.causeError();
    this.time = time;
    this.instantMode = instantMode;
    this.maxWaitTime = maxWaitTime;
    this.insure = typeof insure === "function" ? insure : undefined;
    this.probeTimeHandler = -1;
    this.devMode = devMode;
    this.extraParam = extraParam;

    this.onLoad();
  }

  onLoad() {
    let maxTryNum = this.maxWaitTime / this.time;
    if (this.maxWaitTime % this.time != 0) {
      const extraTime = this.maxWaitTime % this.time;
      maxTryNum = (this.maxWaitTime - extraTime) / this.time;
      this.iterLimit = extraTime > this.time / 2 ? maxTryNum++ : maxTryNum;
    }
    this.iterLimit = maxTryNum;
    if (typeof this.purpose == "function") {
      this.condition = this.purpose;
    }
  }

  causeError() {
    return () => {
      console.log(
        "",
        "GetAsyncDomUtil",
        `Please check callback function is a true functin.`,
        1
      );
    };
  }

  async probe() {
    this.devMode &&
      console.log(`[LOG]UtilsBundle > getAsyncDom: 开始探测 ${this.target}。`);
    const re = (
      fn: (...e: any) => any,
      insure: (() => unknown) | undefined
    ) => {
      return new Promise((resolve) => {
        const targetDom = document.querySelector(this.target);
        let response;
        const a = Boolean(targetDom);
        const b =
          typeof this.condition == "function"
            ? (response = this.condition(targetDom, this.extraParam))
            : this.condition;
        if (a && b) {
          this.index = 0;
          this.devMode &&
            console.log(
              `[LOG]UtilsBundle > getAsyncDom: ${this.target}加载。`,
              targetDom
            );
          resolve(fn(response));
        } else {
          if (this.index > this.iterLimit) {
            this.index = 0;
            this.devMode &&
              console.log(
                `[LOG]UtilsBundle > getAsyncDom: 没找到符合条件的 ${this.target} 。`
              );
            resolve(insure == undefined ? false : insure());
            return;
          }
          this.index++;
          this.probeTimeHandler = window.setTimeout(() => {
            this.instantMode ? "" : (this.time += 500);
            this.devMode &&
              console.log(
                `[LOG]UtilsBundle > getAsyncDom: 正在探测 ${this.target} - 第${this.index}次。`
              );
            resolve(re(this.fn, this.insure));
          }, this.time);
        }
      });
    };
    return await re(this.fn, this.insure);
  }

  /**
   * 模仿莫老板写的getAsyncDom，大概原汁原味？
   * @param {string} target
   * @param {()=>any} fn
   * @param {number} time
   * @param {boolean} isDev
   * @example GetAsyncDomUtil.getAsyncDom(".ac-comment-list",function(){ console.log("2333") })
   */
  static getAsyncDom(target: string, fn: () => any, time = 2500, isDev = true) {
    new GetAsyncDomUtil(
      target,
      fn,
      null,
      "exist",
      time,
      true,
      30000,
      isDev
    ).probe();
  }
}
